﻿using Furion.DependencyInjection;
using Furion.FriendlyException;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using YFurion.Localization;
using YFurion.Localization.Extensions;

namespace YFurion.DataFilters
{
    public class DataFilter : IDataFilter, IScoped
    {
        public IReadOnlyList<DataFilterConfiguration> Filters
        {
            get { return _filters.ToImmutableList(); }
        }
        private readonly List<DataFilterConfiguration> _filters;
        private readonly ILocalizationManager _localizationManager;

        protected IDataFilterOptions DataFilterOptions { get; }

        public DataFilter
        (
            ILocalizationManager localizationManager,
            IDataFilterOptions dataFilterOptions
        )
        {
            _localizationManager = localizationManager;
            foreach (DataFilterConfiguration item in StartupConfiguration.DataFilterOptions.Filters)
            {
                if (dataFilterOptions.Filters.FirstOrDefault(filter => filter.FilterName.Equals(item.FilterName)) == null)
                {
                    dataFilterOptions.RegisterFilter(item.FilterName, item.IsEnabled);
                }
            }
            DataFilterOptions = dataFilterOptions;
            _filters = DataFilterOptions.Filters.ToList();
        }

        public IDisposable EnableFilter(params string[] filterNames)
        {
            var enabledFilters = new List<string>();

            foreach (var filterName in filterNames)
            {
                var filterIndex = GetFilterIndex(filterName);
                if (!_filters[filterIndex].IsEnabled)
                {
                    enabledFilters.Add(filterName);
                    _filters[filterIndex] = new DataFilterConfiguration(_filters[filterIndex], true);
                }
            }

            return new DisposeAction(() => DisableFilter(enabledFilters.ToArray()));
        }

        public IDisposable DisableFilter(params string[] filterNames)
        {
            var disabledFilters = new List<string>();

            foreach (var filterName in filterNames)
            {
                var filterIndex = GetFilterIndex(filterName);
                if (_filters[filterIndex].IsEnabled)
                {
                    disabledFilters.Add(filterName);
                    _filters[filterIndex] = new DataFilterConfiguration(_filters[filterIndex], false);
                }
            }

            return new DisposeAction(() => EnableFilter(disabledFilters.ToArray()));
        }

        public bool IsFilterEnabled(string filterName)
        {
            return GetFilter(filterName).IsEnabled;
        }

        public bool HasFilter(string filterName)
        {
            var filterIndex = _filters.FindIndex(f => f.FilterName == filterName);
            return filterIndex >= 0;
        }

        public IDisposable SetFilterParameter(string filterName, string parameterName, object value)
        {
            var filterIndex = GetFilterIndex(filterName);

            var newfilter = new DataFilterConfiguration(_filters[filterIndex]);

            object oldValue = null;
            var hasOldValue = newfilter.FilterParameters.ContainsKey(parameterName);
            if (hasOldValue)
            {
                oldValue = newfilter.FilterParameters[parameterName];
            }

            newfilter.FilterParameters[parameterName] = value;

            _filters[filterIndex] = newfilter;

            return new DisposeAction(() =>
            {
                if (hasOldValue)
                {
                    SetFilterParameter(filterName, parameterName, oldValue);
                }
            });
        }

        private int GetFilterIndex(string filterName)
        {
            var filterIndex = _filters.FindIndex(f => f.FilterName == filterName);
            if (filterIndex < 0)
            {
                throw Oops.Oh(string.Format(_localizationManager.GetCurrentString("请确保在此之前已注册筛选器"), filterName));
            }

            return filterIndex;
        }

        private DataFilterConfiguration GetFilter(string filterName)
        {
            var filter = _filters.FirstOrDefault(f => f.FilterName == filterName);
            if (filter == null)
            {
                throw Oops.Oh(string.Format(_localizationManager.GetCurrentString("请确保在此之前已注册筛选器"), filterName));
            }

            return filter;
        }
    }
}
